package com.reservation.service.impl;

import com.reservation.dto.user.order.CancelReservation;
import com.reservation.dto.user.order.RefundConfirmDTO;
import com.reservation.exception.BaseException;
import com.reservation.mapper.OrderMapper;
import com.reservation.service.OrderService;
import com.reservation.utils.CurrentHolderUtil;
import com.reservation.vo.user.order.GetAllOrderVO;
import com.reservation.vo.user.order.GetWaitPayOrderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

@Service
@Slf4j

public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Override
    public List<GetAllOrderVO> getAllOrders() {

        int userId = CurrentHolderUtil.getCurrentId();
        List<GetAllOrderVO> list = orderMapper.getAllOrderVOList(userId);

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");

        list.forEach(vo -> {
            // 解析原始日期时间
            LocalDateTime startDateTime = LocalDateTime.parse(vo.getDate(), dateTimeFormatter);
            LocalDateTime endDateTime = LocalDateTime.parse(vo.getTime(), dateTimeFormatter);
            // 更新 date 和 time 字段
            vo.setDate(startDateTime.format(dateFormatter));
            vo.setTime(startDateTime.format(timeFormatter) + "-" + endDateTime.format(timeFormatter));


            String equipmentString = vo.getEquipmentString();
            String content = equipmentString.substring(1, equipmentString.length() - 1);
            String[] equipment = content.split("\",\"");
            for (int i = 0; i < equipment.length; i++) {
                equipment[i] = equipment[i].replace("\"", "");
            }
            vo.setEquipment(equipment);
        });

        return list;
    }

    @Override
    public List<GetWaitPayOrderVO> getWaitPayOrder() {

        int userId = CurrentHolderUtil.getCurrentId();
        List<GetWaitPayOrderVO> list = orderMapper.getWaitPayOrderVOList(userId);

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        LocalDateTime now = LocalDateTime.now();
        list.forEach(vo -> {
            // 解析原始日期时间字符串为 LocalDateTime
            LocalDateTime startDateTime = LocalDateTime.parse(vo.getDate(), dateTimeFormatter);
            LocalDateTime endDateTime = LocalDateTime.parse(vo.getTime(), dateTimeFormatter);
            LocalDateTime targetTime = LocalDateTime.parse(vo.getRemainingTimeString(), dateTimeFormatter);
            // 更新 date 和 time 字段
            vo.setDate(startDateTime.format(dateFormatter));
            vo.setTime(startDateTime.format(timeFormatter) + "-" + endDateTime.format(timeFormatter));
            long secondsRemaining = Duration.between(now, targetTime).getSeconds();     // 计算剩余秒数（如果未来时间）
            // 更新为剩余秒数字符串
            vo.setRemainingTime(Integer.parseInt(String.valueOf(secondsRemaining)));


            log.info("vo: {}", vo);
            String equipmentString = vo.getEquipmentString();
            String content = equipmentString.substring(1, equipmentString.length() - 1);
            String[] equipment = content.split("\",\"");
            for (int i = 0; i < equipment.length; i++) {
                equipment[i] = equipment[i].replace("\"", "");
            }
            vo.setEquipment(equipment);
        });

        return list;
    }

    @Override
    public List<GetAllOrderVO> getCancelableOrderList() {

        int userId = CurrentHolderUtil.getCurrentId();
        List<GetAllOrderVO> list = orderMapper.getCancelableOrderList(userId);

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");

        list.forEach(vo -> {
            // 解析原始日期时间
            LocalDateTime startDateTime = LocalDateTime.parse(vo.getDate(), dateTimeFormatter);
            LocalDateTime endDateTime = LocalDateTime.parse(vo.getTime(), dateTimeFormatter);
            // 更新 date 和 time 字段
            vo.setDate(startDateTime.format(dateFormatter));
            vo.setTime(startDateTime.format(timeFormatter) + "-" + endDateTime.format(timeFormatter));

            String equipmentString = vo.getEquipmentString();
            String content = equipmentString.substring(1, equipmentString.length() - 1);
            String[] equipment = content.split("\",\"");
            for (int i = 0; i < equipment.length; i++) {
                equipment[i] = equipment[i].replace("\"", "");
            }
            vo.setEquipment(equipment);
        });

        return list;
    }

    @Override
    @Transactional
    public boolean cancelOrder(CancelReservation cancelReservation) {

        int userId = CurrentHolderUtil.getCurrentId();
        cancelReservation.setUserID(String.valueOf(userId));

        SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = outputFormat.format(cancelReservation.getTime());
        cancelReservation.setTimeString(dateString);

        int flag1 = orderMapper.setBookingsStates(cancelReservation);
        int flag2 = orderMapper.insertToCancellationRequests(cancelReservation);
        return flag1 > 0 && flag2 > 0;
    }

    @Override
    public List<GetAllOrderVO> getWaitAuditOrderList() {
        int userId = CurrentHolderUtil.getCurrentId();
        List<GetAllOrderVO> list = orderMapper.getWaitAuditOrder1(userId);
        List<GetAllOrderVO> list1 = orderMapper.getWaitAuditOrder2(userId);

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");

        list.forEach(vo -> {
            LocalDateTime startDateTime = LocalDateTime.parse(vo.getDate(), dateTimeFormatter);
            LocalDateTime endDateTime = LocalDateTime.parse(vo.getTime(), dateTimeFormatter);
            vo.setDate(startDateTime.format(dateFormatter));
            vo.setTime(startDateTime.format(timeFormatter) + "-" + endDateTime.format(timeFormatter));

            String equipmentString = vo.getEquipmentString();
            String content = equipmentString.substring(1, equipmentString.length() - 1);
            String[] equipment = content.split("\",\"");
            for (int i = 0; i < equipment.length; i++) {
                equipment[i] = equipment[i].replace("\"", "");
            }
            vo.setEquipment(equipment);
        });
        list1.forEach(vo -> {
            LocalDateTime startDateTime = LocalDateTime.parse(vo.getDate(), dateTimeFormatter);
            LocalDateTime endDateTime = LocalDateTime.parse(vo.getTime(), dateTimeFormatter);
            vo.setDate(startDateTime.format(dateFormatter));
            vo.setTime(startDateTime.format(timeFormatter) + "-" + endDateTime.format(timeFormatter));

            String equipmentString = vo.getEquipmentString();
            String content = equipmentString.substring(1, equipmentString.length() - 1);
            String[] equipment = content.split("\",\"");
            for (int i = 0; i < equipment.length; i++) {
                equipment[i] = equipment[i].replace("\"", "");
            }
            vo.setEquipment(equipment);
        });

        list.addAll(list1);

        return list;
    }

    @Override
    @Transactional
    public boolean confirmCancelOrder(RefundConfirmDTO refundConfirmDTO) {
        log.info("确认取消预约并处理退款：{}", refundConfirmDTO);

        if (refundConfirmDTO == null || refundConfirmDTO.getId() == null) {
            throw new BaseException("订单ID不能为空");
        }

        Long orderId = refundConfirmDTO.getId();

        // 计算退款金额和退款比例
        double refundPercentage = calculateRefundPercentage(orderId);
        double refundAmount = calculateRefundAmount(orderId, refundPercentage);


        // 1. 更新订单状态为已取消并退款(5)
        int updateResult = orderMapper.setConfirmCancelReservation(orderId);
        if (updateResult <= 0) {
            log.error("更新订单状态失败，订单ID: {}", orderId);
            throw new BaseException("确认取消失败，请重试");
        }

        try {
            // 2. 获取用户ID和支付方式
            Long userId = orderMapper.getUserIdByOrderId(orderId);
            Integer payMethod = orderMapper.getOrderPayMethod(orderId);

            if (userId == null || payMethod == null) {
                log.error("获取用户信息或支付方式失败, 订单ID: {}", orderId);
                throw new BaseException("获取订单信息失败");
            }

            // 3. 更新用户钱包余额
            int walletResult = orderMapper.updateUserWalletIncrease(userId, refundAmount, payMethod);
            if (walletResult <= 0) {
                log.error("更新用户钱包余额失败, 用户ID: {}, 订单ID: {}", userId, orderId);
                throw new BaseException("更新钱包余额失败");
            }

            log.info("退款处理成功, 订单ID: {}, 用户ID: {}, 退款金额: {}", orderId, userId, refundAmount);
            return true;
        } catch (Exception e) {
            log.error("退款处理失败", e);
            throw new BaseException("退款处理失败: " + e.getMessage());
        }
    }

    /**
     * 计算退款比例
     *
     * @param id 订单ID
     * @return 退款比例（0-1之间的小数）
     */
    private double calculateRefundPercentage(Long id) {
        // 根据预订开始时间与当前时间的差距来确定退款比例
        // 获取预订开始时间
        java.time.LocalDateTime startTime = orderMapper.getOrderStartTime(id);
        if (startTime == null) {
            log.error("无法获取订单开始时间, 订单ID: {}", id);
            throw new BaseException("无法获取订单信息");
        }

        // 计算开始时间与当前时间的小时差
        long hoursDiff = java.time.Duration.between(java.time.LocalDateTime.now(), startTime).toHours();

        // 距离开始时间超过72小时，全额退款
        if (hoursDiff >= 72) {
            return 1.0;
        }
        // 距离开始时间48-72小时，退款75%
        else if (hoursDiff >= 48) {
            return 0.75;
        }
        // 距离开始时间24-48小时，退款25%
        else if (hoursDiff >= 24) {
            return 0.25;
        }
        // 距离开始时间小于24小时，不退款
        else {
            return 0.0;
        }
    }

    /**
     * 计算退款金额
     *
     * @param id               订单ID
     * @param refundPercentage 退款比例
     * @return 退款金额
     */
    private double calculateRefundAmount(Long id, double refundPercentage) {
        // 从数据库获取订单总金额，并计算退款金额
        Double totalAmount = orderMapper.getOrderTotalAmount(id);
        if (totalAmount == null) {
            log.error("无法获取订单总金额, 订单ID: {}", id);
            throw new BaseException("无法获取订单信息");
        }

        return totalAmount * refundPercentage;
    }

}
